package com.goat.model.manager;

import com.goat.model.element.BaseElement;
import com.goat.model.element.Enemy;
import com.goat.model.element.MapObj;
import com.goat.model.element.Player;
import com.goat.model.manager.enumCls.GameElement;

import javax.swing.*;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * 模拟加载器，实质上是一个工具类，专门用来加载文件，自身并没有逻辑
 */

public class GameLoader {
    private static final EleManager eleManager=EleManager.getEleManager();

    private static Map<String,ImageIcon> imageIconMap=new HashMap<>();
    //合金弹头的图片复杂很多，要用一个list来存储
    private static Map<String,List<ImageIcon>> hejiandantouMap=new HashMap<>();

    private static Properties properties=new Properties();
    /**
     * 加载地图的方法
     * @param mapId  要加载哪一张地图
     */
    public static void MapLoad(int mapId){
        String mapName="com/goat/text/"+mapId+".map";
        //1.类加载器
        ClassLoader classLoader = GameLoader.class.getClassLoader();
        //2.通过类加载器来获取指定地图路径的IO流
        InputStream maps = classLoader.getResourceAsStream(mapName);
        if (maps==null){
            System.out.println("配置文件读取失败");
            return;
        }
        properties.clear();//因为这些方法循环被调用，所以这里也要clear
        try {
            //配置文件类载入IO流
            properties.load(maps);
            //这个Enumeration就是properties中key的集合
            Enumeration<?> names=properties.propertyNames();
            while (names.hasMoreElements()){
                //将key转为String类型
                String key = names.nextElement().toString();
                //下面的代码是为了改变为MapObj传入字符串的格式
                //e.g:"BRICK,80,100"
                String[] split = properties.getProperty(key).split(";");
                for (int i = 0; i < split.length; i++) {
                    BaseElement element = new MapObj().createElement(key + "," + split[i]);
                    //将地图对象加入元素管理器
                    List<BaseElement> mapList = eleManager.getGameElements().get(GameElement.MAP);
                    mapList.add(element);
                }
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static Map<String, ImageIcon> getImageIconMap() {
        return imageIconMap;
    }

    //加载图片
    public static void ImageLoad(){
        String textUrl="com/goat/text/GameData.pro";//file's name should be more 规律
        //1.类加载器
        ClassLoader classLoader = GameLoader.class.getClassLoader();
        //2.通过类加载器来获取指定图片路径的IO流
        InputStream texts = classLoader.getResourceAsStream(textUrl);
        //imageIconMap用于存放数据
        properties.clear();//先释放掉刚刚加载地图的数据
        try {
            properties.load(texts);
            Set<Object> set = properties.keySet();
            for (Object o :set) {
                String url = properties.getProperty(o.toString());
                imageIconMap.put(o.toString(),new ImageIcon(url));
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    //载入Player
    public static void PlayerLoad() {
        String str="500,500";//初始位置
        //各扫门前雪，初始化的工作交由Player的createElement方法自己做
        BaseElement player = new Player().createElement(str);
        eleManager.getGameElements().get(GameElement.PLAYER).add(player);
    }

    public static void EnemyLoad() {
        Random random = new Random();
        for (int i = 0; i < 5; i++) {
            int x = random.nextInt(800);
            int y = random.nextInt(500);
            BaseElement element = createInstance("Enemy").createElement(x+","+y);
            eleManager.getGameElements().get(GameElement.ENEMY).add(element);
        }
    }

    //添加一个构造方法，代替new，根据配置文件的类名来创建一个对应类实例
    //模拟实现一个框架，Spring
    //高度解耦
    /**
     *
     * @param clsName 传入类名字符串
     * @return  根据传入的字符串返回一个对象
     */
    public static BaseElement createInstance(String clsName){
        Properties properties1 = new Properties();
        //具体实现：根据反射机制创建一个类实例
        String textUrl="com/goat/text/Class.pro";//存储类名-类全限定符的配置文件
        //1.类加载器
        ClassLoader classLoader = GameLoader.class.getClassLoader();
        //2.通过类加载器来获取指定图片路径的IO流
        InputStream texts = classLoader.getResourceAsStream(textUrl);
        Object o1=null;
        try {
            properties1.load(texts);
            Set<Object> set = properties1.keySet();
            for (Object o :set) {
                //System.out.println(o);
                String cls = properties1.getProperty(o.toString());
                //System.out.println(cls);
                o1 = Class.forName(cls).newInstance();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }


        if(o1 instanceof BaseElement){
            return (BaseElement) o1;
        }else {
            return null;
        }
    }



    //加载坦克，退出历史舞台
    //Totally 不应该的写法。载入器Load就好，instead 在载入器中为元素赋值
    //其实也没错，它这里也是交给了Player的Constructor来赋值的
    public static void TankLoad(){
        //载入图片
        ImageIcon imageIcon=new ImageIcon("image/tank/play1/player1_up.png");
        //实例化对象，参数其实是读配置文件的
        BaseElement baseElement=new Player(100,100,50,50,imageIcon);
        //放入管理器
        Map<GameElement, List<BaseElement>> gameElements = eleManager.getGameElements();
        gameElements.get(GameElement.PLAYER).add(baseElement);

        for (int i = 0; i < 5; i++) {
            gameElements.get(GameElement.ENEMY).add(new Enemy().createElement(""));
        }
    }
}
